#include<iostream>
#include<vector>
using namespace std;


#define ATRIBUT 10
/*
o clasa template pentru intrarile din arborele director
clientul LDAP foloseste aceste atribute atunci cand creeaza o intrare
sau cauta anumite atribute
clasa prevede specializari pentru pointeri si char*;

*/

template<class T>class Atribut
{
	char *nume;//numele atributului
	T atrValue;//valoarea atributului
public:
	Atribut(char *nume,T atr)
	{
		this->nume=new char[strlen(nume)+1];
		if(this->nume==0)
			throw new exception();
		strcpy(this->nume,nume);
		atrValue=atr;
	}

	Atribut()
	{
		nume=0;
	}

	Atribut(const Atribut<T>& atribut)
	{
		this->nume=new char[strlen(atribut.nume)+1];
		if(this->nume==0)
			throw new exception();
		strcpy(this->nume,atribut.nume);
		atrValue=atribut.atrValue;
	}

	Atribut<T>& operator=(const Atribut<T>& atribut)
	{
		if(this!=&atribut)
		{
			if(this->nume!=0)
				delete[] this->nume;
			this->nume=new char[strlen(atribut.nume)+1];
			if(this->nume==0)
				throw new exception();
			strcpy(this->nume,atribut.nume);
			atrValue=atribut.atrValue;
		}
		return (*this);
	}

	~Atribut()
	{
		if(nume!=0)
			delete[] nume;
	}

	T daAtribut()const
	{
		return atrValue;
	}

	void setValue(T atrNou)
	{
		atrValue=atrNou;
	}

	void setNume(char *numeNou)
	{
		if(nume!=0)
			delete[] nume;
		nume=new char[strlen(numeNou)+1];
		strcpy(nume,numeNou);
	}

	void setAtribut(char *numeNou,T atrNou)
	{
		setValue(atrNou);
		setNume(numeNou);
	}

	char* daNume()const
	{
		return nume;
	}

};

/******************************  specializari******************************************/

template<class T>class Atribut<T*>
{
	char *nume;
	T* atrValue;
public:
	Atribut(char *nume,T* atr)
	{
		this->nume=new char[strlen(nume)+1];
		if(this->nume==0)
			throw new exception();
		strcpy(this->nume,nume);
		atrValue=new T((*atr));
	}

	Atribut()
	{
		nume=0;
		atrValue=0;
	}

	~Atribut()
	{
		if(nume!=0)
			delete[] nume;
		if(atrValue!=0)
			delete atrValue;
	}

	
	Atribut(const Atribut<T*>& atribut)
	{
		this->nume=new char[strlen(atribut.nume)+1];
		if(this->nume==0)
			throw new exception;
		strcpy(this->nume,atribut.nume);
		atrValue=new T((*atribut.atrValue));
	}

	Atribut<T*>& operator=(const Atribut<T*>& atribut)
	{
		if(this!=&atribut)
		{
			if(this->nume!=0)
				delete[] this->nume;
			this->nume=new char[strlen(atribut.nume)+1];
			if(this->nume==0)
				throw new exception;
			strcpy(this->nume,atribut.nume);
			atrValue=new T((*atribut.atrValue));
		}
		return (*this);
	}

	T *daAtribut()const
	{
		return new T((*atrValue));
	}

	void setValue(T *atrNou)
	{
		if(atrValue!=0)
			delete atrValue;
		atrValue=new T((*atrNou));
	}

	void setNume(char *numeNou)
	{
		if(nume!=0)
			delete[] nume;
		nume=new char[strlen(numeNou)+1];
		strcpy(nume,numeNou);
	}

	void setAtribut(char *numeNou,T *atrNou)
	{
		setValue(atrNou);
		setNume(numeNou);
	}

	char* daNume()const
	{
		return nume;
	}

};

/**************** specializarea pentru char*       *************************/

template<>class Atribut<char*>
{
	char *nume;
	char* atrValue;
public:
	Atribut(char *nume,char* atr)
	{
		this->nume=new char[strlen(nume)+1];
		if(this->nume==0)
			throw new exception();
		strcpy(this->nume,nume);
		atrValue=new char[strlen(atr)+1];
		if(atrValue==0)
			throw new exception();
		strcpy(atrValue,atr);
	}

	Atribut()
	{
		nume=0;
		atrValue=0;
	}

	~Atribut()
	{
		if(nume!=0)
			delete[] nume;
		if(atrValue!=0)
			delete[] atrValue;
	}

	Atribut(const Atribut<char*>& atribut)
	{
		this->nume=new char[strlen(atribut.nume)+1];
		if(this->nume==0)
			throw new exception;
		strcpy(this->nume,atribut.nume);
		atrValue=new char[strlen(atribut.atrValue)+1];
		if(atrValue==0)
			throw new exception();
		strcpy(atrValue,atribut.atrValue);
	}

	Atribut<char*>& operator=(const Atribut<char*>& atribut)
	{
		if(this!=&atribut)
		{
			if(this->nume!=0)
				delete[] this->nume;
			this->nume=new char[strlen(atribut.nume)+1];
			if(this->nume==0)
				throw new exception;
			strcpy(this->nume,atribut.nume);
			atrValue=new char[strlen(atribut.atrValue)+1];
			if(atrValue==0)
				throw new exception();
			strcpy(atrValue,atribut.atrValue);
		}
		return (*this);
	}


	char *daAtribut()const
	{
		return atrValue;
	}

	void setValue(char *atrNou)
	{
		if(atrValue!=0)
			delete atrValue;
		atrValue=new char[strlen(atrNou)+1];
		if(atrValue==0)
			throw new exception();
		strcpy(atrValue,atrNou);
	}

	void setNume(char *numeNou)
	{
		if(nume!=0)
			delete[] nume;
		nume=new char[strlen(numeNou)+1];
		strcpy(nume,numeNou);
	}

	void setAtribut(char *numeNou,char *atrNou)
	{
		setValue(atrNou);
		setNume(numeNou);
	}

	char* daNume()const
	{
		return nume;
	}

};